package algorithm_demo.demo04.graph;

import java.util.*;

/**
 * 图的拓扑排序算法
 * 1. 在图中找到所有入度为0的点输出
 * 2. 把所有入度为0的点在图中删除掉，继续找入度为0的点输出，周而复始
 * 3. 图的所有点都被删除后，依次输出的顺序就是拓扑排序
 * 要求：有向图且其中没有环
 * 应用：事件安排、编译顺序
 *
 * @author Api
 * @date 2023/2/19 9:50
 */
public class Code03_TopologicalOrderingOfGraphs {


    public static List<Node> sortedTopology(Graph graph) {
        //key：某一个node
        //value：剩余的入度
        Map<Node, Integer> inMap = new HashMap<>();
        //剩余入度为0的点，才能进这个队列
        Queue<Node> zeroInQueue = new LinkedList<>();
        for (Node node : graph.nodes.values()) {
            inMap.put(node, node.in);
            if (node.in == 0) {
                zeroInQueue.add(node);
            }
        }
        //拓扑排序的结果，依次加入result
        List<Node> result = new ArrayList<>();
        while (!zeroInQueue.isEmpty()) {
            Node cur = zeroInQueue.poll();
            result.add(cur);
            for (Node next : cur.nexts) {
                inMap.put(next, inMap.get(next) - 1);
                if (inMap.get(next) == 0) {
                    zeroInQueue.add(next);
                }
            }
        }
        return result;
    }
}
